package com.ssy.lingxi.member.merchant.serviceimpl.base;

import com.ssy.lingxi.common.constant.basic.EnableDisableStatus;
import com.ssy.lingxi.common.constant.member.MemberLevelTypeEnum;
import com.ssy.lingxi.common.constant.member.MemberTypeEnum;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.member.merchant.api.constant.MemberRelationTypeEnum;
import com.ssy.lingxi.member.merchant.api.model.constant.MemberProcessTypeEnum;
import com.ssy.lingxi.member.merchant.config.ServiceConfig;
import com.ssy.lingxi.member.merchant.entity.*;
import com.ssy.lingxi.member.merchant.model.bo.AgentAreaBO;
import com.ssy.lingxi.member.merchant.model.bo.AreaBO;
import com.ssy.lingxi.member.merchant.model.bo.WorkflowTaskListBO;
import com.ssy.lingxi.member.merchant.model.bo.WorkflowTaskResultBO;
import com.ssy.lingxi.member.merchant.model.constant.*;
import com.ssy.lingxi.member.merchant.model.dto.CountryAreaDTO;
import com.ssy.lingxi.member.merchant.model.vo.basic.request.AreaCodeVO;
import com.ssy.lingxi.member.merchant.model.vo.basic.response.*;
import com.ssy.lingxi.member.merchant.model.vo.platform.response.RoleRuleManageVO;
import com.ssy.lingxi.member.merchant.model.vo.validate.response.WorkFlowStepVO;
import com.ssy.lingxi.member.merchant.repository.*;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberDepositDetailService;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberHistoryService;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberValidateService;
import com.ssy.lingxi.member.merchant.service.feign.IMessageFeignService;
import com.ssy.lingxi.member.merchant.service.feign.IPayFeignService;
import com.ssy.lingxi.member.merchant.service.feign.IReportFeignService;
import com.ssy.lingxi.member.merchant.service.feign.IWorkflowFeignService;
import com.ssy.lingxi.member.merchant.utils.AgentAreaUtil;
import com.ssy.lingxi.member.merchant.utils.NumberUtil;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 会员审核、资料入库基础服务接口实现类
 * @author 万宁
 * @version 2.0.0
 * @date 2020-09-14
 */
@Service
public class BaseMemberValidateServiceImpl implements IBaseMemberValidateService {
    @Resource
    private MemberTypeRepository memberTypeRepository;

    @Resource
    private RoleRepository roleRepository;

    @Resource
    private CountryAreaRepository countryAreaRepository;

    @Resource
    private MemberRelationRepository relationRepository;

    @Resource
    private ChannelTypeRepository channelTypeRepository;

    @Resource
    private IBaseMemberDepositDetailService baseMemberDepositDetailService;

    @Resource
    private IBaseMemberHistoryService baseMemberHistoryService;

    @Resource
    private IWorkflowFeignService workflowFeignService;

    @Resource
    private IPayFeignService payFeignService;

    @Resource
    private IReportFeignService reportFeignService;

    @Resource
    private IMessageFeignService messageFeignService;


    /**
     * 根据创建下级会员的规则，查询下级会员的会员类型列表
     *
     * @param memberTypeEnum 上级会员的会员类型枚举
     * @return 查询结果
     */
    @Override
    public List<MemberTypeIdAndNameVO> getSubMemberTypeList(Integer memberTypeEnum) {
        if(memberTypeEnum.equals(MemberTypeEnum.MERCHANT.getCode()) || memberTypeEnum.equals(MemberTypeEnum.MERCHANT_PERSONAL.getCode())) {
            return memberTypeRepository.findByTypeEnumOrTypeEnum(MemberTypeEnum.MERCHANT.getCode(), MemberTypeEnum.MERCHANT_PERSONAL.getCode(), Sort.by("id").ascending()).stream().map(memberTypeDO -> new MemberTypeIdAndNameVO(memberTypeDO.getId(), MemberTypeEnum.getCodeMessage(memberTypeDO.getTypeEnum()))).collect(Collectors.toList());
        } else if(memberTypeEnum.equals(MemberTypeEnum.CHANNEL.getCode()) || memberTypeEnum.equals(MemberTypeEnum.CHANNEL_PERSONAL.getCode())) {
            return memberTypeRepository.findByTypeEnumOrTypeEnum(MemberTypeEnum.CHANNEL.getCode(), MemberTypeEnum.CHANNEL_PERSONAL.getCode(), Sort.by("id").ascending()).stream().map(memberTypeDO -> new MemberTypeIdAndNameVO(memberTypeDO.getId(), MemberTypeEnum.getCodeMessage(memberTypeDO.getTypeEnum()))).collect(Collectors.toList());
        } else {
            return new ArrayList<>();
        }
    }

    /**
     * 根据创建下级会员的规则，查询下级会员的会员类型列表(SASS)
     *
     * @param memberTypeEnum   上级会员的会员类型枚举
     * @param roleManageVOList 会员适用角色list
     * @return 查询结果
     */
    @Override
    public List<MemberTypeIdAndNameVO> getSubMemberTypeList(Integer memberTypeEnum, List<RoleRuleManageVO> roleManageVOList) {
        if (memberTypeEnum.equals(MemberTypeEnum.MERCHANT.getCode()) || memberTypeEnum.equals(MemberTypeEnum.MERCHANT_PERSONAL.getCode())) {
            return roleManageVOList.stream().filter(roleManageVO -> roleManageVO.getMemberTypeEnum().equals(MemberTypeEnum.MERCHANT.getCode()) || roleManageVO.getMemberTypeEnum().equals(MemberTypeEnum.MERCHANT_PERSONAL.getCode()))
                    .map(roleManageVO -> new MemberTypeIdAndNameVO(roleManageVO.getMemberTypeId(), roleManageVO.getMemberTypeName())).distinct().collect(Collectors.toList());
        } else if (memberTypeEnum.equals(MemberTypeEnum.CHANNEL.getCode()) || memberTypeEnum.equals(MemberTypeEnum.CHANNEL_PERSONAL.getCode())) {
            return roleManageVOList.stream().filter(roleManageVO -> roleManageVO.getMemberTypeEnum().equals(MemberTypeEnum.CHANNEL.getCode()) || roleManageVO.getMemberTypeEnum().equals(MemberTypeEnum.CHANNEL_PERSONAL.getCode()))
                    .map(roleManageVO -> new MemberTypeIdAndNameVO(roleManageVO.getMemberTypeId(), roleManageVO.getMemberTypeName())).distinct().collect(Collectors.toList());
        } else {
            return new ArrayList<>();
        }
    }

    /**
     * 平台会员审核外部流程定义
     *
     * @param roleName 角色名称
     * @return 步骤列表
     */
    @Override
    public List<WorkFlowStepVO> getPlatformValidateOuterSteps(String roleName) {
        return Stream.of(new WorkFlowStepVO(1, MemberStringEnum.MEMBER_APPLY.getName(), roleName), new WorkFlowStepVO(2, MemberStringEnum.MEMBER_VALIDATE.getName(), MemberStringEnum.PLATFORM_ROLE_NAME.getName())).collect(Collectors.toList());
    }

    /**
     * 会员入库审核外部流程定义
     *
     * @param relationDO 会员关系
     * @return 步骤列表
     */
    @Override
    public List<WorkFlowStepVO> getMemberDepositOuterSteps(MemberRelationDO relationDO) {
        //如果是会员创建的下级会员，申请角色和审核角色都是上级会员角色
        return relationDO.getRelSource().equals(MemberRelationSourceEnum.MEMBER_CREATE.getCode()) ? getMemberDepositOuterSteps(relationDO.getRole().getRoleName(), relationDO.getRole().getRoleName()) : getMemberDepositOuterSteps(relationDO.getRole().getRoleName(), relationDO.getSubRoleName());
    }

    /**
     * 会员入库审核外部流程定义
     *
     * @param roleName    上级角色名称
     * @param subRoleName 下级角色名称
     * @return 步骤列表
     */
    @Override
    public List<WorkFlowStepVO> getMemberDepositOuterSteps(String roleName, String subRoleName) {
        return Stream.of(new WorkFlowStepVO(1, MemberStringEnum.APPLY_FOR_DEPOSITORY.getName(), subRoleName), new WorkFlowStepVO(2, MemberStringEnum.VALIDATE_DEPOSITORY.getName(), roleName)).collect(Collectors.toList());
    }

    /**
     * 会员变更审核外部流程定义
     *
     * @param relationDO 会员关系
     * @return 步骤列表
     */
    @Override
    public List<WorkFlowStepVO> getMemberModifyOuterSteps(MemberRelationDO relationDO) {
        return Stream.of(new WorkFlowStepVO(1, MemberStringEnum.APPLY_FOR_CHANGE.getName(), relationDO.getSubRoleName()), new WorkFlowStepVO(2, MemberStringEnum.VALIDATE_CHANGE.getName(), relationDO.getRole().getRoleName())).collect(Collectors.toList());
    }

    /**
     * 添加角色时，检验角色是否符合规则定义
     *
     * @param roleDO         被检验的角色
     * @param memberTypeEnum 会员类型枚举，定义在MemberTypeEnum和MemberTypeDO中
     * @return 检验结果
     */
    @Override
    public Wrapper<Void> checkRoleWithMemberType(RoleDO roleDO, Integer memberTypeEnum) {
        switch (MemberTypeEnum.toEnum(memberTypeEnum)) {
            case MERCHANT:
                if (!roleDO.getMemberType().getTypeEnum().equals(MemberTypeEnum.CHANNEL.getCode()) && !roleDO.getMemberType().getTypeEnum().equals(MemberTypeEnum.MERCHANT.getCode())) {
                    return Wrapper.fail(ResponseCode.MC_MS_MERCHANT_CAN_ADD_MERCHANT_OR_CHANNEL_ROLE);
                }
                break;
            case MERCHANT_PERSONAL:
                if (!roleDO.getMemberType().getTypeEnum().equals(MemberTypeEnum.CHANNEL_PERSONAL.getCode()) && !roleDO.getMemberType().getTypeEnum().equals(MemberTypeEnum.MERCHANT_PERSONAL.getCode())) {
                    return Wrapper.fail(ResponseCode.MC_MS_MERCHANT_PERSONAL_CAN_ADD_MERCHANT_PERSONAL_OR_CHANNEL_PERSONAL_ROLE);
                }
                break;
            case CHANNEL:
                if (!roleDO.getMemberType().getTypeEnum().equals(MemberTypeEnum.MERCHANT.getCode()) && !roleDO.getMemberType().getTypeEnum().equals(MemberTypeEnum.CHANNEL.getCode())) {
                    return Wrapper.fail(ResponseCode.MC_MS_CHANNEL_CAN_ADD_MERCHANT_OR_CHANNEL_ROLE);
                }
                break;
            case CHANNEL_PERSONAL:
                if (!roleDO.getMemberType().getTypeEnum().equals(MemberTypeEnum.MERCHANT_PERSONAL.getCode()) && !roleDO.getMemberType().getTypeEnum().equals(MemberTypeEnum.CHANNEL_PERSONAL.getCode())) {
                    return Wrapper.fail(ResponseCode.MC_MS_CHANNEL_PERSONAL_CAN_ADD_MERCHANT_OR_CHANNEL_PERSONAL_ROLE);
                }
            default:
                break;
        }

        return Wrapper.success();
    }

    /**
     * 查询流程步骤定义
     *
     * @param relationDO 会员关系
     * @return 查询结果
     */
    @Override
    public Wrapper<WorkflowTaskListBO> getMemberProcessSteps(MemberRelationDO relationDO) {
        if(relationDO.getValidateTask() == null) {
            return Wrapper.fail(ResponseCode.MC_MC_MEMBER_PROCESS_DATA_ERROR);
        }

        WorkflowTaskListBO taskListBO = new WorkflowTaskListBO();

        Wrapper<WorkflowTaskListBO> result = workflowFeignService.listMemberProcessSteps(relationDO.getMemberId(), relationDO.getValidateTask().getProcessKey(), relationDO.getValidateTask().getTaskId());
        if(result.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(result.getCode(), result.getMessage());
        }

        taskListBO.setStepList(result.getData().getStepList());

        if(StringUtils.hasLength(relationDO.getValidateTask().getTaskId())) {
            taskListBO.setCurrentStep(result.getData().getCurrentStep());
        } else {
            result.getData().getStepList().stream().max(Comparator.comparingInt(WorkFlowStepVO::getStep)).ifPresent(workFlowStepVO -> taskListBO.setCurrentStep(workFlowStepVO.getStep()));
        }

        if(relationDO.getValidateTask().getProcessTypeEnum().equals(MemberProcessTypeEnum.MEMBER_DEPOSITORY.getCode())) {
            taskListBO.setProcessName(MemberStringEnum.MEMBER_DEPOSIT_INNER_PROCESS.getName());
        }

        if(relationDO.getValidateTask().getProcessTypeEnum().equals(MemberProcessTypeEnum.MEMBER_MODIFICATION.getCode())) {
            taskListBO.setProcessName(MemberStringEnum.MEMBER_CHANGE_INNER_PROCESS.getName());
        }

        return Wrapper.success(taskListBO);
    }

    /**
     * 根据创建下级会员的规则，查询下级会员的角色列表
     *
     * @param memberTypeEnum 上级会员的会员类型枚举
     * @return 查询结果
     */
    @Override
    public List<RoleIdAndNameVO> getSubRoleList(Integer memberTypeEnum) {
        if(memberTypeEnum.equals(MemberTypeEnum.MERCHANT.getCode()) || memberTypeEnum.equals(MemberTypeEnum.MERCHANT_PERSONAL.getCode())) {
            Specification<RoleDO> specification = (Specification<RoleDO>) (root, query, criteriaBuilder) -> {
                List<Predicate> list = new ArrayList<>();
                list.add(criteriaBuilder.notEqual(root.get("relType").as(Integer.class), MemberRelationTypeEnum.PLATFORM.getCode()));
                Join<RoleDO, MemberTypeDO> memberTypeJoin = root.join("memberType", JoinType.LEFT);
                list.add(criteriaBuilder.or(criteriaBuilder.equal(memberTypeJoin.get("typeEnum").as(Integer.class), MemberTypeEnum.MERCHANT.getCode()), criteriaBuilder.equal(memberTypeJoin.get("typeEnum").as(Integer.class), MemberTypeEnum.MERCHANT_PERSONAL.getCode())));
                Predicate[] p = new Predicate[list.size()];
                return criteriaBuilder.and(list.toArray(p));
            };
            return roleRepository.findAll(specification, Sort.by("id").ascending()).stream().map(roleDO -> new RoleIdAndNameVO(roleDO.getId(), roleDO.getRoleName())).collect(Collectors.toList());
        } else if(memberTypeEnum.equals(MemberTypeEnum.CHANNEL.getCode()) || memberTypeEnum.equals(MemberTypeEnum.CHANNEL_PERSONAL.getCode())) {
            Specification<RoleDO> specification = (Specification<RoleDO>) (root, query, criteriaBuilder) -> {
                List<Predicate> list = new ArrayList<>();
                list.add(criteriaBuilder.notEqual(root.get("relType").as(Integer.class), MemberRelationTypeEnum.PLATFORM.getCode()));
                Join<RoleDO, MemberTypeDO> memberTypeJoin = root.join("memberType", JoinType.LEFT);
                list.add(criteriaBuilder.or(criteriaBuilder.equal(memberTypeJoin.get("typeEnum").as(Integer.class), MemberTypeEnum.CHANNEL.getCode()), criteriaBuilder.equal(memberTypeJoin.get("typeEnum").as(Integer.class), MemberTypeEnum.CHANNEL_PERSONAL.getCode())));
                Predicate[] p = new Predicate[list.size()];
                return criteriaBuilder.and(list.toArray(p));
            };
            return roleRepository.findAll(specification, Sort.by("id").ascending()).stream().map(roleDO -> new RoleIdAndNameVO(roleDO.getId(), roleDO.getRoleName())).collect(Collectors.toList());
        } else {
            return new ArrayList<>();
        }
    }

    /**
     * 根据创建下级会员的规则，查询下级会员的角色列表(SAAS)
     *
     * @param memberTypeEnum   上级会员的会员类型枚举
     * @param roleManageVOList 会员适用角色list
     * @return 查询结果
     */
    @Override
    public List<RoleIdAndNameVO> getSubRoleList(Integer memberTypeEnum, List<RoleRuleManageVO> roleManageVOList) {
        if (memberTypeEnum.equals(MemberTypeEnum.MERCHANT.getCode()) || memberTypeEnum.equals(MemberTypeEnum.MERCHANT_PERSONAL.getCode())) {
            return roleManageVOList.stream().filter(roleManageVO -> roleManageVO.getMemberTypeEnum().equals(MemberTypeEnum.MERCHANT.getCode()) || roleManageVO.getMemberTypeEnum().equals(MemberTypeEnum.MERCHANT_PERSONAL.getCode()))
                    .map(roleManageVO -> new RoleIdAndNameVO(roleManageVO.getRoleId(), roleManageVO.getRoleName())).distinct().collect(Collectors.toList());
        } else if (memberTypeEnum.equals(MemberTypeEnum.CHANNEL.getCode()) || memberTypeEnum.equals(MemberTypeEnum.CHANNEL_PERSONAL.getCode())) {
            return roleManageVOList.stream().filter(roleManageVO -> roleManageVO.getMemberTypeEnum().equals(MemberTypeEnum.CHANNEL.getCode()) || roleManageVO.getMemberTypeEnum().equals(MemberTypeEnum.CHANNEL_PERSONAL.getCode()))
                    .map(roleManageVO -> new RoleIdAndNameVO(roleManageVO.getRoleId(), roleManageVO.getRoleName())).distinct().collect(Collectors.toList());
        } else {
            return new ArrayList<>();
        }
    }

    /**
     * 根据上级会员Id，查询代理省列表
     * @param upperRelationId 上级会员关系Id
     * @return 返回信息
     */
    @Override
    public Wrapper<List<CountryAreaCodeNameVO>> getProvinceList(Long upperRelationId) {
        List<CountryAreaCodeNameVO> result;
        if(NumberUtil.isNullOrZero(upperRelationId)) {
            List<CountryAreaDTO> dtoList = countryAreaRepository.findByLevel(ServiceConfig.COUNTRY_AREA_PROVINCE_LEVEL, Sort.by("code").ascending(), CountryAreaDTO.class);
            result = dtoList.stream().map(dto -> new CountryAreaCodeNameVO(dto.getCode(), dto.getName())).collect(Collectors.toList());
            result.add(0, new CountryAreaCodeNameVO(ServiceConfig.COUNTRY_AREA_TOP_CODE, MemberStringEnum.ALL.getName()));
        } else {
            MemberRelationDO relationDO = relationRepository.findById(upperRelationId).orElse(null);
            if(relationDO == null || !relationDO.getSubMemberLevelTypeEnum().equals(MemberLevelTypeEnum.CHANNEL.getCode()) || relationDO.getChannel() == null || relationDO.getChannel().getAgentArea() == null) {
                return Wrapper.fail(ResponseCode.MC_MS_AGENT_CHANNEL_AREA_NOT_EXIST);
            }

            MemberChannelDO channelDO = relationDO.getChannel();
            if(CollectionUtils.isEmpty(channelDO.getAgentArea().getAreas()) || channelDO.getAgentArea().getAreas().stream().anyMatch(countryAreaBO -> countryAreaBO.getProvinceCode().equals(ServiceConfig.COUNTRY_AREA_TOP_CODE))) {
                List<CountryAreaDTO> dtoList = countryAreaRepository.findByLevel(ServiceConfig.COUNTRY_AREA_PROVINCE_LEVEL, Sort.by("code").ascending(), CountryAreaDTO.class);
                result = dtoList.stream().map(dto -> new CountryAreaCodeNameVO(dto.getCode(), dto.getName())).collect(Collectors.toList());
                result.add(0, new CountryAreaCodeNameVO(ServiceConfig.COUNTRY_AREA_TOP_CODE, MemberStringEnum.ALL.getName()));
            } else {
                result = channelDO.getAgentArea().getAreas().stream().map(countryAreaBO -> new CountryAreaCodeNameVO(countryAreaBO.getProvinceCode(), countryAreaBO.getProvince())).sorted(Comparator.comparing(CountryAreaCodeNameVO::getCode)).collect(Collectors.toList());
            }
        }
        return Wrapper.success(result);
    }

    /**
     * 根据上级会员Id和省编码，查询代理市列表
     *
     * @param upperRelationId 上级会员关系Id
     * @param provinceCode 省编码
     * @return 返回信息
     */
    @Override
    public Wrapper<List<CountryAreaCodeNameVO>> getCityList(Long upperRelationId, String provinceCode) {
        List<CountryAreaCodeNameVO> result;

        if(provinceCode.equals(ServiceConfig.COUNTRY_AREA_TOP_CODE)) {
            result = Stream.of(new CountryAreaCodeNameVO("", MemberStringEnum.CHOOSE.getName())).collect(Collectors.toList());
        } else {
            if(NumberUtil.isNullOrZero(upperRelationId)) {
                List<CountryAreaDTO> dtoList = countryAreaRepository.findByParentCode(provinceCode, Sort.by("code").ascending(), CountryAreaDTO.class);
                result = dtoList.stream().map(dto -> new CountryAreaCodeNameVO(dto.getCode(), dto.getName())).collect(Collectors.toList());
                result.add(0, new CountryAreaCodeNameVO("", MemberStringEnum.CHOOSE.getName()));
            } else {
                MemberRelationDO relationDO = relationRepository.findById(upperRelationId).orElse(null);
                if(relationDO == null || !relationDO.getSubMemberLevelTypeEnum().equals(MemberLevelTypeEnum.CHANNEL.getCode()) || relationDO.getChannel() == null || relationDO.getChannel().getAgentArea() == null) {
                    return Wrapper.fail(ResponseCode.MC_MS_AGENT_CHANNEL_AREA_NOT_EXIST);
                }

                List<AreaBO> agentAreaBOList = relationDO.getChannel().getAgentArea().getAreas().stream().filter(countryAreaBO -> countryAreaBO.getProvinceCode().equals(provinceCode)).collect(Collectors.toList());
                if(CollectionUtils.isEmpty(agentAreaBOList)) {
                    return Wrapper.fail(ResponseCode.MC_MS_AGENT_CHANNEL_AREA_NOT_EXIST);
                }

                if(agentAreaBOList.stream().anyMatch(countryAreaBO -> !StringUtils.hasLength(countryAreaBO.getCityCode()))) {
                    List<CountryAreaDTO> dtoList = countryAreaRepository.findByParentCode(provinceCode, Sort.by("code").ascending(), CountryAreaDTO.class);
                    result = dtoList.stream().map(dto -> new CountryAreaCodeNameVO(dto.getCode(), dto.getName())).collect(Collectors.toList());
                    result.add(0, new CountryAreaCodeNameVO("", MemberStringEnum.CHOOSE.getName()));
                } else {
                    result = agentAreaBOList.stream().map(countryAreaBO -> new CountryAreaCodeNameVO(countryAreaBO.getCityCode(), countryAreaBO.getCity())).collect(Collectors.toList());
                }
            }
        }

        return Wrapper.success(result);
    }

    /**
     * 查询渠道类型列表
     *
     * @return 查询结果
     */
    @Override
    public List<ChannelTypeIdAndNameVO> getChannelTypes() {
        return channelTypeRepository.findAll(Sort.by("id").ascending()).stream().map(channelTypeDO -> new ChannelTypeIdAndNameVO(channelTypeDO.getId(), MemberChannelTypeEnum.getMsg(channelTypeDO.getChannelTypeEnum()))).collect(Collectors.toList());
    }

    /**
     * 查询上级会员Id和名称列表
     *
     * @param subMemberId 下级会员Id
     * @param subRoleId   下级会员角色Id
     * @return 查询结果
     */
    @Override
    public List<UpperRelationIdAndNameVO> getUpperRelationList(Long subMemberId, Long subRoleId) {
        List<MemberRelationDO> relationList = relationRepository.findBySubMemberIdAndSubRoleIdAndRelType(subMemberId, subRoleId, MemberRelationTypeEnum.OTHER.getCode());
        return CollectionUtils.isEmpty(relationList) ? Stream.of(new UpperRelationIdAndNameVO(0L, "")).collect(Collectors.toList()) : relationList.stream().map(relationDO -> new UpperRelationIdAndNameVO(relationDO.getId(), relationDO.getMember().getName().concat("(").concat(relationDO.getRole().getRoleName()).concat(")"))).sorted(Comparator.comparingLong(UpperRelationIdAndNameVO::getUpperRelationId)).collect(Collectors.toList());
    }


    /**
     * 根据会员类型，查询角色列表（排除“平台”角色）
     *
     * @param memberTypeId 会员类型Id
     * @return 查询结果
     */
    @Override
    public List<RoleIdAndNameVO> getRoleListByMemberType(Long memberTypeId) {
        Specification<RoleDO> specification = (Specification<RoleDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.notEqual(root.get("relType").as(Integer.class), MemberRelationTypeEnum.PLATFORM.getCode()));
            list.add(criteriaBuilder.equal(root.get("status").as(Integer.class), EnableDisableStatus.ENABLE.getCode()));
            Join<RoleDO, MemberTypeDO> memberTypeJoin = root.join("memberType", JoinType.LEFT);
            list.add(criteriaBuilder.equal(memberTypeJoin.get("id").as(Long.class), memberTypeId));
            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        return roleRepository.findAll(specification, Sort.by("id").ascending()).stream().map(roleDO -> new RoleIdAndNameVO(roleDO.getId(), roleDO.getRoleName())).collect(Collectors.toList());
    }


    /**
     * 检查并生成新的渠道信息（用于新增下级会员）
     * @param upperRelationId 上级会员关系Id
     * @param subMemberId 当前会员Id
     * @param subRoleId   当前会员角色Id
     * @param channelTypeId 渠道类型Id
     * @param areas  代理区域
     * @param remark 备注信息
     * @return 操作结果
     */
    @Override
    public Wrapper<MemberChannelDO> checkChannelAgentAreas(Long upperRelationId, Long subMemberId, Long subRoleId, Long channelTypeId, List<AreaCodeVO> areas, String remark) {
        if(NumberUtil.isNullOrNegative(upperRelationId)) {
            return Wrapper.fail(ResponseCode.MC_MS_UPPER_MEMBER_ID_MUST_GTE_ZERO);
        }

        //检查渠道
        ChannelTypeDO channelTypeDO = channelTypeRepository.findById(channelTypeId).orElse(null);
        if(channelTypeDO == null) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_CHANNEL_TYPE_DOES_NOT_EXIST);
        }

        if(CollectionUtils.isEmpty(areas)) {
            return Wrapper.fail(ResponseCode.MC_MS_AGENT_AREAS_CAN_NOT_BE_EMPTY);
        }

        AgentAreaBO agentAreaBO;

        //如果上级会员Id为0，说明当前会员是顶级渠道，从省市表中判断代理区域的数据
        //如果上级会员Id不为0，说明当前会员是下级渠道，找到与上级会员的关系，从中获得当前渠道的代理区域进行判断
        //查询当前会员的上级会员（由于在会员添加角色，或创建下级会员中有规则限定，所以如果当前会员是渠道会员的话，其上级会员也是渠道会员
        List<MemberRelationDO> relationDOList = relationRepository.findBySubMemberIdAndSubRoleIdAndRelType(subMemberId, subRoleId, MemberRelationTypeEnum.OTHER.getCode());
        if(upperRelationId.equals(0L)) {
            if(!CollectionUtils.isEmpty(relationDOList)) {
                return Wrapper.fail(ResponseCode.MC_MS_UPPER_MEMBER_ID_MUST_GTE_ZERO);
            }

            List<String> codeList = areas.stream().flatMap(areaCodeVO -> {
                if(StringUtils.hasLength(areaCodeVO.getCityCode())) {
                    return Stream.of(areaCodeVO.getProvinceCode(), areaCodeVO.getCityCode());
                } else {
                    return Stream.of(areaCodeVO.getProvinceCode());
                }
            }).distinct().collect(Collectors.toList());
            List<CountryAreaDTO> dtoList = countryAreaRepository.findByCodeIn(codeList, CountryAreaDTO.class);

            if(codeList.size() != dtoList.size()) {
                return Wrapper.fail(ResponseCode.MC_MS_COUNTRY_AREA_DOES_NOT_EXIST);
            }

            agentAreaBO = AgentAreaUtil.transferToBO(upperRelationId, areas, dtoList);
        } else {
            MemberRelationDO upperChannelRelation = relationDOList.stream().filter(relation -> relation.getId().equals(upperRelationId)).findFirst().orElse(null);
            if(upperChannelRelation == null) {
                return Wrapper.fail(ResponseCode.MC_MS_UPPER_CHANNEL_MEMBER_NOT_EXIST);
            }

            if(upperChannelRelation.getChannel() == null || upperChannelRelation.getChannel().getAgentArea() == null) {
                return Wrapper.fail(ResponseCode.MC_MS_UPPER_CHANNEL_AGENT_AREAS_DOES_NOT_EXIST);
            }

            if(AgentAreaUtil.listNotIncluded(upperChannelRelation.getChannel().getAgentArea(), areas)) {
                return Wrapper.fail(ResponseCode.MC_MS_AGENT_AREAS_BEYOND_UPPER_MEMBER_AREAS);
            }

            agentAreaBO = AgentAreaUtil.transferToBO(upperRelationId, areas, upperChannelRelation.getChannel().getAgentArea());
        }

        MemberChannelDO channelDO = new MemberChannelDO();
        channelDO.setChannelType(channelTypeDO);
        channelDO.setLevel(ServiceConfig.MEMBER_CHANNEL_DEFAULT_LEVEL);
        channelDO.setChannelLevelTag(MemberStringEnum.MEMBER_CHANNEL_DEFAULT_LEVEL_TAG.getName());
        channelDO.setAgentArea(agentAreaBO);
        channelDO.setRemark(StringUtils.hasLength(remark) ? remark : "");
        return Wrapper.success(channelDO);
    }

    /**
     * 检查并修改渠道信息（用于修改下级会员）
     *
     * @param relationDO  会员关系
     * @param upperRelationId 上级会员关系Id
     * @param subMemberId     当前会员Id
     * @param subRoleId       当前会员角色Id
     * @param channelTypeId   渠道类型Id
     * @param areas           代理区域
     * @param remark          备注信息
     * @return 操作结果
     */
    @Override
    public Wrapper<Void> updateChannelAgentAreas(MemberRelationDO relationDO, Long upperRelationId, Long subMemberId, Long subRoleId, Long channelTypeId, List<AreaCodeVO> areas, String remark) {
        if(NumberUtil.isNullOrNegative(upperRelationId)) {
            return Wrapper.fail(ResponseCode.MC_MS_UPPER_MEMBER_ID_MUST_GTE_ZERO);
        }

        //检查渠道
        ChannelTypeDO channelTypeDO = channelTypeRepository.findById(channelTypeId).orElse(null);
        if(channelTypeDO == null) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_CHANNEL_TYPE_DOES_NOT_EXIST);
        }

        if(CollectionUtils.isEmpty(areas)) {
            return Wrapper.fail(ResponseCode.MC_MS_AGENT_AREAS_CAN_NOT_BE_EMPTY);
        }

        AgentAreaBO agentAreaBO;

        //如果上级会员Id为0，说明当前会员是顶级渠道，从省市表中判断代理区域的数据
        //如果上级会员Id不为0，说明当前会员是下级渠道，找到与上级会员的关系，从中获得当前渠道的代理区域进行判断
        //查询当前会员的上级会员（由于在会员添加角色，或创建下级会员中有规则限定，所以如果当前会员是渠道会员的话，其上级会员也是渠道会员
        List<MemberRelationDO> relationDOList = relationRepository.findBySubMemberIdAndSubRoleIdAndRelType(subMemberId, subRoleId, MemberRelationTypeEnum.OTHER.getCode());
        if(upperRelationId.equals(0L)) {
            if(!CollectionUtils.isEmpty(relationDOList)) {
                return Wrapper.fail(ResponseCode.MC_MS_UPPER_MEMBER_ID_MUST_GTE_ZERO);
            }

            List<String> codeList = areas.stream().flatMap(areaCodeVO -> {
                if(StringUtils.hasLength(areaCodeVO.getCityCode())) {
                    return Stream.of(areaCodeVO.getProvinceCode(), areaCodeVO.getCityCode());
                } else {
                    return Stream.of(areaCodeVO.getProvinceCode());
                }
            }).distinct().collect(Collectors.toList());
            List<CountryAreaDTO> dtoList = countryAreaRepository.findByCodeIn(codeList, CountryAreaDTO.class);

            if(codeList.size() != dtoList.size()) {
                return Wrapper.fail(ResponseCode.MC_MS_COUNTRY_AREA_DOES_NOT_EXIST);
            }

            agentAreaBO = AgentAreaUtil.transferToBO(upperRelationId, areas, dtoList);
        } else {
            MemberRelationDO upperChannelRelation = relationDOList.stream().filter(relation -> relation.getId().equals(upperRelationId)).findFirst().orElse(null);
            if(upperChannelRelation == null) {
                return Wrapper.fail(ResponseCode.MC_MS_UPPER_CHANNEL_MEMBER_NOT_EXIST);
            }

            if(upperChannelRelation.getChannel() == null || upperChannelRelation.getChannel().getAgentArea() == null) {
                return Wrapper.fail(ResponseCode.MC_MS_UPPER_CHANNEL_AGENT_AREAS_DOES_NOT_EXIST);
            }

            if(AgentAreaUtil.listNotIncluded(upperChannelRelation.getChannel().getAgentArea(), areas)) {
                return Wrapper.fail(ResponseCode.MC_MS_AGENT_AREAS_BEYOND_UPPER_MEMBER_AREAS);
            }

            agentAreaBO = AgentAreaUtil.transferToBO(upperRelationId, areas, upperChannelRelation.getChannel().getAgentArea());
        }


        relationDO.getChannel().setChannelType(channelTypeDO);
        relationDO.getChannel().setLevel(ServiceConfig.MEMBER_CHANNEL_DEFAULT_LEVEL);
        relationDO.getChannel().setChannelLevelTag(MemberStringEnum.MEMBER_CHANNEL_DEFAULT_LEVEL_TAG.getName());
        relationDO.getChannel().setAgentArea(agentAreaBO);
        relationDO.getChannel().setRemark(StringUtils.hasLength(remark) ? remark : "");
        relationRepository.saveAndFlush(relationDO);
        return Wrapper.success();
    }

    /**
     * 根据上级会员Id检查代理区域，并更新relationDo关联的MemberChannelDO中的信息（未保存，调用方需要保存relationDO）
     * @param relationDO 会员关系
     * @param upperRelationId 上级会员Id
     * @param channelTypeId 渠道类型Id
     * @param areas 代理区域
     * @param remark 渠道备注信息
     * @return 检查结果
     */
    @Override
    public Wrapper<Void> checkAndUpdateChannelAgentAreas(MemberRelationDO relationDO, Long upperRelationId, Long channelTypeId, List<AreaCodeVO> areas, String remark) {
        if(NumberUtil.isNullOrNegative(upperRelationId)) {
            return Wrapper.fail(ResponseCode.MC_MS_UPPER_MEMBER_ID_MUST_GTE_ZERO);
        }

        //检查渠道
        ChannelTypeDO channelTypeDO = channelTypeRepository.findById(channelTypeId).orElse(null);
        if(channelTypeDO == null) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_CHANNEL_TYPE_DOES_NOT_EXIST);
        }

        if(CollectionUtils.isEmpty(areas)) {
            return Wrapper.fail(ResponseCode.MC_MS_AGENT_AREAS_CAN_NOT_BE_EMPTY);
        }

        AgentAreaBO agentAreaBO;

        //如果上级会员Id为0，说明当前会员是顶级渠道，从省市表中判断代理区域的数据
        //如果上级会员Id不为0，说明当前会员是下级渠道，找到与上级会员的关系，从中获得当前渠道的代理区域进行判断
        //查询当前会员的上级会员（由于在会员添加角色，或创建下级会员中有规则限定，所以如果当前会员是渠道会员的话，其上级会员也是渠道会员
        List<MemberRelationDO> relationDOList = relationRepository.findBySubMemberIdAndSubRoleIdAndRelType(relationDO.getMemberId(), relationDO.getRoleId(), MemberRelationTypeEnum.OTHER.getCode());
        if(upperRelationId.equals(0L)) {
            if(!CollectionUtils.isEmpty(relationDOList)) {
                return Wrapper.fail(ResponseCode.MC_MS_UPPER_MEMBER_ID_MUST_GTE_ZERO);
            }

            List<String> codeList = areas.stream().flatMap(areaCodeVO -> {
                if(StringUtils.hasLength(areaCodeVO.getCityCode())) {
                    return Stream.of(areaCodeVO.getProvinceCode(), areaCodeVO.getCityCode());
                } else {
                    return Stream.of(areaCodeVO.getProvinceCode());
                }
            }).distinct().collect(Collectors.toList());
            List<CountryAreaDTO> dtoList = countryAreaRepository.findByCodeIn(codeList, CountryAreaDTO.class);

            if(codeList.size() != dtoList.size()) {
                return Wrapper.fail(ResponseCode.MC_MS_COUNTRY_AREA_DOES_NOT_EXIST);
            }

            agentAreaBO = AgentAreaUtil.transferToBO(upperRelationId, areas, dtoList);
        } else {
            MemberRelationDO upperChannelRelation = relationDOList.stream().filter(relation -> relation.getId().equals(upperRelationId)).findFirst().orElse(null);
            if(upperChannelRelation == null) {
                return Wrapper.fail(ResponseCode.MC_MS_UPPER_CHANNEL_MEMBER_NOT_EXIST);
            }

            if(upperChannelRelation.getChannel() == null || upperChannelRelation.getChannel().getAgentArea() == null) {
                return Wrapper.fail(ResponseCode.MC_MS_UPPER_CHANNEL_AGENT_AREAS_DOES_NOT_EXIST);
            }

            if(AgentAreaUtil.listNotIncluded(upperChannelRelation.getChannel().getAgentArea(), areas)) {
                return Wrapper.fail(ResponseCode.MC_MS_AGENT_AREAS_BEYOND_UPPER_MEMBER_AREAS);
            }

            agentAreaBO = AgentAreaUtil.transferToBO(upperRelationId, areas, upperChannelRelation.getChannel().getAgentArea());
        }

        relationDO.getChannel().setChannelType(channelTypeDO);
        relationDO.getChannel().setAgentArea(agentAreaBO);
        relationDO.getChannel().setRemark(StringUtils.hasLength(remark) ? remark.trim() : "");
        return Wrapper.success();
    }



    /**
     * 批量执行审核
     * @param loginUser 登录用户
     * @param validateIds 审核内容Id列表
     * @param innerStatusEnum 匹配的内部状态
     * @return 审核结果
     */
    @Override
    public Wrapper<Void> batchExecMemberProcess(UserLoginCacheDTO loginUser, List<Long> validateIds, MemberInnerStatusEnum innerStatusEnum) {
        return batchExecMemberProcess(loginUser, validateIds, Stream.of(innerStatusEnum).collect(Collectors.toList()));
    }

    /**
     * 批量入库、资料审核
     *
     * @param loginUser        登录用户
     * @param validateIds      审核内容Id列表
     * @param innerStatusEnums 匹配的内部状态列表
     * @return 审核结果
     */
    @Override
    public Wrapper<Void> batchExecMemberProcess(UserLoginCacheDTO loginUser, List<Long> validateIds, List<MemberInnerStatusEnum> innerStatusEnums) {
        if(CollectionUtils.isEmpty(validateIds)) {
            return Wrapper.success();
        }

        List<MemberRelationDO> relationList = relationRepository.findAllById(validateIds);
        if(relationList.size() != validateIds.size()) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        if(relationList.stream().anyMatch(relationDO -> relationDO.getValidateTask() == null || !StringUtils.hasLength(relationDO.getValidateTask().getProcessKey()))) {
            return Wrapper.fail(ResponseCode.MC_MC_MEMBER_PROCESS_DATA_ERROR);
        }

        //TaskId如果为空，说明流程已经结束
        if(relationList.stream().anyMatch(relationDO -> !StringUtils.hasLength(relationDO.getValidateTask().getTaskId()))) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_VALIDATE_HAS_COMPLETED);
        }

        //检查状态
        List<Integer> innerStatusCodes = innerStatusEnums.stream().map(MemberInnerStatusEnum::getCode).collect(Collectors.toList());
        if(relationList.stream().anyMatch(relationDO -> !innerStatusCodes.contains(relationDO.getInnerStatus()))) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_VALIDATE_STATUS_INCORRECT);
        }

        for (MemberRelationDO relationDO : relationList) {
            Wrapper<Void> result = execMemberProcess(loginUser, relationDO, MemberValidateAgreeEnum.AGREE.getCode(), "", innerStatusEnums);
            if(result.getCode() != ResponseCode.SUCCESS.getCode()) {
                return result;
            }
        }

        return Wrapper.success();
    }

    /**
     * 执行入库、资料变更流程
     * @param loginUser 登录用户
     * @param validateId 会员关系Id
     * @param agree  审核结果 0-不通过， 1-通过
     * @param reason 审核意见
     * @return 执行结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> execMemberProcess(UserLoginCacheDTO loginUser, Long validateId, Integer agree, String reason, MemberInnerStatusEnum innerStatusEnum) {
        MemberRelationDO relationDO = relationRepository.findById(validateId).orElse(null);
        if(relationDO == null || !relationDO.getMemberId().equals(loginUser.getMemberId()) || !relationDO.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        if(relationDO.getValidateTask() == null || !StringUtils.hasLength(relationDO.getValidateTask().getProcessKey())) {
            return Wrapper.fail(ResponseCode.MC_MC_MEMBER_PROCESS_DATA_ERROR);
        }

        //审核不通过的原因不能为空
        if(agree.equals(MemberValidateAgreeEnum.DISAGREE.getCode()) && !StringUtils.hasLength(reason)) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_VALIDATE_DISAGREE_REASON_CAN_NOT_BE_EMPTY);
        }

        //TaskId如果为空，说明流程已经结束
        if(!StringUtils.hasLength(relationDO.getValidateTask().getTaskId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_VALIDATE_HAS_COMPLETED);
        }

        //检查状态
        if(!innerStatusEnum.getCode().equals(relationDO.getInnerStatus())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_VALIDATE_STATUS_INCORRECT);
        }

        return execMemberProcess(loginUser, relationDO, agree, reason, Stream.of(innerStatusEnum).collect(Collectors.toList()));
    }

    /**
     * 执行入库、资料变更流程
     *
     * @param loginUser        登录用户
     * @param validateId       会员关系Id
     * @param agree            审核结果 0-不通过， 1-通过
     * @param reason           审核意见
     * @param innerStatusEnums 匹配的内部状态列表
     * @return 执行结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> execMemberProcess(UserLoginCacheDTO loginUser, Long validateId, Integer agree, String reason, List<MemberInnerStatusEnum> innerStatusEnums) {
        MemberRelationDO relationDO = relationRepository.findById(validateId).orElse(null);
        if(relationDO == null || !relationDO.getMemberId().equals(loginUser.getMemberId()) || !relationDO.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        if(relationDO.getValidateTask() == null || !StringUtils.hasLength(relationDO.getValidateTask().getProcessKey())) {
            return Wrapper.fail(ResponseCode.MC_MC_MEMBER_PROCESS_DATA_ERROR);
        }

        //审核不通过的原因不能为空
        if(agree.equals(MemberValidateAgreeEnum.DISAGREE.getCode()) && !StringUtils.hasText(reason)) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_VALIDATE_DISAGREE_REASON_CAN_NOT_BE_EMPTY);
        }

        //TaskId如果为空，说明流程已经结束
        if(!StringUtils.hasLength(relationDO.getValidateTask().getTaskId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_VALIDATE_HAS_COMPLETED);
        }

        //检查状态
        if(innerStatusEnums.stream().noneMatch(innerStatusEnum -> innerStatusEnum.getCode().equals(relationDO.getInnerStatus()))) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_VALIDATE_STATUS_INCORRECT);
        }

        return execMemberProcess(loginUser, relationDO, agree, reason, innerStatusEnums);
    }

    /**
     * 执行入库、资料变更流程
     *
     * @param loginUser       登录用户
     * @param relationDO      会员关系
     * @param agree           审核结果 0-不通过， 1-通过
     * @param reason          不通过的原因
     * @param innerStatusEnum 匹配的内部状态
     * @return 执行结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> execMemberProcess(UserLoginCacheDTO loginUser, MemberRelationDO relationDO, Integer agree, String reason, MemberInnerStatusEnum innerStatusEnum) {
        if(relationDO.getValidateTask() == null || !StringUtils.hasLength(relationDO.getValidateTask().getProcessKey())) {
            return Wrapper.fail(ResponseCode.MC_MC_MEMBER_PROCESS_DATA_ERROR);
        }

        //审核不通过的原因不能为空
        if(agree.equals(MemberValidateAgreeEnum.DISAGREE.getCode()) && !StringUtils.hasLength(reason)) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_VALIDATE_DISAGREE_REASON_CAN_NOT_BE_EMPTY);
        }

        //TaskId如果为空，说明流程已经结束
        if(!StringUtils.hasLength(relationDO.getValidateTask().getTaskId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_VALIDATE_HAS_COMPLETED);
        }

        //检查状态
        if(!innerStatusEnum.getCode().equals(relationDO.getInnerStatus())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_VALIDATE_STATUS_INCORRECT);
        }

        return execMemberProcess(loginUser, relationDO, agree, reason, Stream.of(innerStatusEnum).collect(Collectors.toList()));
    }

    /**
     * 执行入库、资料变更流程
     * @param loginUser 登录用户
     * @param relationDO 会员关系
     * @param agree    审核结果 0-不通过， 1-通过
     * @param reason   不通过的原因
     * @param innerStatusEnums 匹配的内部状态列表
     * @return 执行结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> execMemberProcess(UserLoginCacheDTO loginUser, MemberRelationDO relationDO, Integer agree, String reason, List<MemberInnerStatusEnum> innerStatusEnums) {
        //记录执行之前的内部状态
        int lastInnerStatus = relationDO.getInnerStatus();
        //执行流程
        Wrapper<WorkflowTaskResultBO> taskResult = workflowFeignService.execMemberProcess(relationDO.getValidateTask().getProcessKey(), relationDO.getValidateTask().getTaskId(), relationDO.getMemberId(), relationDO.getRoleId(), relationDO.getId(), agree);
        if(taskResult.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(taskResult.getCode(), taskResult.getMessage());
        }

        relationDO.setInnerStatus(taskResult.getData().getInnerStatus());
        relationDO.getValidateTask().setTaskId(taskResult.getData().getTaskId());

        //如果入库审核通过或不通过，修改外部状态
        if(taskResult.getData().getInnerStatus().equals(MemberInnerStatusEnum.VERIFY_PASSED.getCode()) || taskResult.getData().getInnerStatus().equals(MemberInnerStatusEnum.VERIFY_NOT_PASSED.getCode())) {
            relationDO.setOuterStatus(taskResult.getData().getInnerStatus().equals(MemberInnerStatusEnum.VERIFY_PASSED.getCode()) ? MemberOuterStatusEnum.DEPOSITORY_PASSED.getCode() : MemberOuterStatusEnum.DEPOSITORY_NOT_PASSED.getCode());

            //入库时间
            relationDO.setDepositTime(taskResult.getData().getInnerStatus().equals(MemberInnerStatusEnum.VERIFY_PASSED.getCode()) ? LocalDateTime.now() : null);

            //如果入库审核通过，表示“曾经审核通过”
            if(taskResult.getData().getInnerStatus().equals(MemberInnerStatusEnum.VERIFY_PASSED.getCode())) {
                relationDO.setVerified(MemberValidateStatusEnum.VERIFY_PASSED.getCode());
            }

            //如果入库审核不通过，记录审核不通过原因
            if(taskResult.getData().getInnerStatus().equals(MemberInnerStatusEnum.VERIFY_NOT_PASSED.getCode())) {
                relationDO.setValidateMsg(reason);
            }

            //通知支付服务
            if(taskResult.getData().getInnerStatus().equals(MemberInnerStatusEnum.VERIFY_PASSED.getCode())) {
                //入库审核通过，将入库资料的版本改为“Using”，否则不处理（继续修改）
                baseMemberDepositDetailService.updateDepositDetailToUsing(relationDO);

                payFeignService.notifyMemberCredit(relationDO.getMemberId(), relationDO.getRoleId(), relationDO.getSubMemberId(), relationDO.getSubRoleId());
                payFeignService.notifyMemberAssetAccount(relationDO.getMemberId(), relationDO.getMember().getName(), relationDO.getRoleId(), relationDO.getRole().getRoleName(), relationDO.getSubMemberId(), relationDO.getSubMember().getName(), relationDO.getSubRoleId(), relationDO.getSubRoleName(), relationDO.getSubMemberLevelTypeEnum(), relationDO.getSubRole().getMemberType().getTypeEnum(), relationDO.getStatus());
            }

            //记录外部历史记录
            baseMemberHistoryService.saveMemberOuterHistory(relationDO, relationDO.getRole().getRoleName(), MemberValidateHistoryOperationEnum.parseString(taskResult.getData().getOperation()), MemberOuterStatusEnum.getCodeMsg(relationDO.getOuterStatus()), reason);

        }

        //如果资料变更审核通过或不通过，修改外部状态
        if(taskResult.getData().getInnerStatus().equals(MemberInnerStatusEnum.MODIFY_PASSED.getCode()) || taskResult.getData().getInnerStatus().equals(MemberInnerStatusEnum.MODIFY_NOT_PASSED.getCode())) {
            relationDO.setOuterStatus(taskResult.getData().getInnerStatus().equals(MemberInnerStatusEnum.MODIFY_PASSED.getCode()) ? MemberOuterStatusEnum.MODIFY_PASSED.getCode() : MemberOuterStatusEnum.MODIFY_NOT_PASSED.getCode());

            //变更审核通过，首先要比较入库资料是否变更，记录变更记录；
            // 再将入库资料的版本改为“Using”，否则不处理（继续修改）
            if(taskResult.getData().getInnerStatus().equals(MemberInnerStatusEnum.MODIFY_PASSED.getCode())) {
                baseMemberDepositDetailService.saveDepositDetailHistory(relationDO);
                baseMemberDepositDetailService.updateDepositDetailToUsing(relationDO);
            }

            //记录外部历史记录
            baseMemberHistoryService.saveMemberOuterHistory(relationDO, relationDO.getRole().getRoleName(), MemberValidateHistoryOperationEnum.parseString(taskResult.getData().getOperation()), MemberOuterStatusEnum.getCodeMsg(relationDO.getOuterStatus()), reason);

        }

        relationRepository.saveAndFlush(relationDO);

        //记录内部审核记录
        baseMemberHistoryService.saveMemberInnerHistory(relationDO, loginUser, MemberValidateHistoryOperationEnum.parseString(taskResult.getData().getOperation()), reason);

        //发送实时消息
        reportFeignService.reportMemberValidate(relationDO.getId(), relationDO.getMemberId(), relationDO.getRoleId(), lastInnerStatus, taskResult.getData().getInnerStatus(), relationDO.getValidateTask().getProcessTypeEnum());
        messageFeignService.sendMemberValidateMessage(relationDO);

        return Wrapper.success();
    }
}
